﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Web.UI;

using Sunyi.Project.WebPoint.BusinessLogic;
using Sunyi.Project.WebPoint.Common;
using Sunyi.Project.WebPoint.DataAccess;

namespace Sunyi.Project.WebPoint.WebControl
{
    internal static class PageAnalyzer
    {
        private static Collection<Type> controlTypeFilter;
        public static Collection<Type> ControlTypeFilter
        {
            get
            {
                if (controlTypeFilter == null) FillControlFilter();

                return controlTypeFilter;
            }
        }

        private static Collection<string> controlTypeNameFilter;
        public static Collection<string> ControlTypeNameFilter
        {
            get
            {
                if (controlTypeNameFilter == null) FillControlFilter();

                return controlTypeNameFilter;
            }
        }

        public static void Analyze(Page page)
        {
            var collectedControls = new Collection<Control>();

            try
            {
                AnalyzeSingleControl(page, collectedControls);

                SavePageControl(page.Request.Path, collectedControls);
            }
            catch (Exception e)
            {
                var log = new DataContract.Log { Level = LogLevel.Error.ToString(), Source = typeof(PageAnalyzer).Name };
                log.UserName = Thread.CurrentThread.Name;
                log.Data = e.ToString();

                Logger.Write(log);
            }
        }

        private static void AnalyzeSingleControl(Control control, Collection<Control> controls)
        {
            bool flag = false;

            foreach (var type in ControlTypeFilter)
            {
                if (type.IsInstanceOfType(control))
                {
                    controls.Add(control);
                    flag = true;
                    break;
                }
            }

            if (!flag)
            {
                Type controlType = control.GetType();
                string controlTypeName = controlType.Namespace + "." + controlType.Name;
                if (ControlTypeNameFilter.Contains(controlTypeName)) controls.Add(control);
            }

            foreach (Control subControl in control.Controls)
            {
                AnalyzeSingleControl(subControl, controls);
            }
        }

        private static void SavePageControl(string pagePath, Collection<Control> controls)
        {
            const string SqlCommandDelete = "DELETE FROM [AT_PageControl] WHERE [PageId] = @PageId";
            const string SqlCommandInsert = "INSERT INTO [AT_PageControl]([PageId], [ControlId], [ControlClientId], [ControlType], [IsActive]) VALUES (@PageId, @ControlId, @ControlClientId, @ControlType, @IsActive)";

            var pageManager = new PageManager();
            WebPoint.DataContract.Page webPointPage = pageManager.SelectByUrl(pagePath);

            if (webPointPage != null)
            {
                var parameters = new Dictionary<string, object>();
                parameters.Add("@PageId", null);
                parameters.Add("@ControlId", null);
                parameters.Add("@ControlClientId", null);
                parameters.Add("@ControlType", null);
                parameters.Add("@IsActive", null);

                var connection = ConnectionProvider.CreateConnection();
                try
                {
                    connection.Open();

                    // Remove exist records.
                    var deleteCommandParameters = new Dictionary<string, object>();
                    deleteCommandParameters.Add("@PageId", webPointPage.Id);
                    DbHelper.ExecuteNonQuery(connection, SqlCommandDelete, deleteCommandParameters);

                    // Insert new records.
                    foreach (Control control in controls)
                    {
                        parameters["@PageId"] = webPointPage.Id.ToString();
                        parameters["@ControlId"] = control.ID;
                        parameters["@ControlClientId"] = control.ClientID;
                        parameters["@ControlType"] = control.GetType().Name;
                        parameters["@IsActive"] = true;

                        DbHelper.ExecuteNonQuery(connection, SqlCommandInsert, parameters);
                    }
                }
                finally
                {
                    connection.Close();
                }
            }
        }

        private static void FillControlFilter()
        {
            if (controlTypeFilter == null)
            {
                controlTypeFilter = new Collection<Type>();
                controlTypeFilter.Add(typeof(System.Web.UI.WebControls.Button));
                controlTypeFilter.Add(typeof(System.Web.UI.WebControls.CheckBox));
                controlTypeFilter.Add(typeof(System.Web.UI.WebControls.CheckBoxList));
                controlTypeFilter.Add(typeof(System.Web.UI.WebControls.DropDownList));
                controlTypeFilter.Add(typeof(System.Web.UI.WebControls.HyperLink));
                controlTypeFilter.Add(typeof(System.Web.UI.WebControls.Image));
                controlTypeFilter.Add(typeof(System.Web.UI.WebControls.ImageButton));
                controlTypeFilter.Add(typeof(System.Web.UI.WebControls.Label));
                controlTypeFilter.Add(typeof(System.Web.UI.WebControls.LinkButton));
                controlTypeFilter.Add(typeof(System.Web.UI.WebControls.ListBox));
                controlTypeFilter.Add(typeof(System.Web.UI.WebControls.RadioButton));
                controlTypeFilter.Add(typeof(System.Web.UI.WebControls.RadioButtonList));
                controlTypeFilter.Add(typeof(System.Web.UI.WebControls.TextBox));
            }

            if (controlTypeNameFilter == null)
            {
                controlTypeNameFilter = new Collection<string>();
                controlTypeNameFilter.Add("Sunyi.Project.WebPoint.WebControl.AttachmentListControl");
            }
        }
    }
}
